package com.sunchangming.uniqname;

import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;

import org.apache.mina.core.session.IoSession;

import com.google.protobuf.BlockingRpcChannel;
import com.google.protobuf.Descriptors.MethodDescriptor;
import com.google.protobuf.Message;
import com.google.protobuf.RpcController;
import com.google.protobuf.ServiceException;

public class RpcChannel implements BlockingRpcChannel {
	volatile private IoSession session;

	public void setSession(IoSession session) {
		this.session = session;
	}

	private final ReentrantLock lock = new ReentrantLock();
	private final Condition con = lock.newCondition();
	/** 受lock保护 */
	private Message res;

	public void setRes(Message res) {
		lock.lock();
		try {
			this.res = res;
			con.signalAll();
		} finally {
			lock.unlock();
		}
	}

	@Override
	public Message callBlockingMethod(MethodDescriptor method, RpcController controller, Message request,
			Message responsePrototype) throws ServiceException {
		lock.lock();
		try {
			this.res = null;
		} finally {
			lock.unlock();
		}

		try {
			if (!session.write(new Res(request, method.getIndex())).await(
					ServiceConfig.getInstance().getRpcClientWriteTimeout(), TimeUnit.SECONDS))
				throw new ServiceException("RPC超时");

			lock.lock();
			try {
				if (this.res == null
						&& !con.await(ServiceConfig.getInstance().getRpcClientWaitTimeout(), TimeUnit.SECONDS))
					throw new ServiceException("RPC超时");
			} finally {
				lock.unlock();
			}
		} catch (InterruptedException e) {
			throw new ServiceException("写入数据失败。", e);
		}

		if (this.res == null) // 把我喊醒了，但是东西没给我？
			throw new ServiceException("服务状态不对");

		return res;
	}

}
